#include "MyComment.h"

char LoginUserName[128] = {0}; // 保存登录的用户名
void showMenu();
int SID;
int ret = 0;
// 工作线程，接受服务器返回来的消息
void *work(void *pArg)
{ // 传入一个套接字
    // 把套接字从地址里面取出来
    int sID = *(int *)pArg;
    // 用户连接后会创建当前线程，并且会把用户的套接字id通过参数传入进来
    // 这里是把套接字从地址里面取出来
    MSG msg;
    struct sockaddr_in clientAddr;
    socklen_t len = sizeof(clientAddr);
    int ret = 0;
    // 接收消息
    while (0 < (ret = recv(sID, &msg, sizeof(MSG), 0)))
    {
        PVCH *pSC = (PVCH *)msg.buf;
        printf("%s:[%s]\n", pSC->selfName, pSC->text);
    }
    if (ret <= 0)
    {
        printf("接受数据出错了，服务器可能被关掉了\n");
    }
}
int Enroll(int sID) // 注册
{
    TEN zhuc;
    printf("请输入用户名 密码 性别 所教学科\n");
    scanf("%s %s %s %s", zhuc.name, zhuc.pwd, zhuc.sex, zhuc.subject);
    MSG msg;
    msg.type = TeacherEnroll;
    memcpy(msg.buf, &zhuc, sizeof(TEN)); // 把注册结构体拷贝到消息结构体的仓库中
    // 把消息发送给服务器
    int ret = send(sID, &msg, sizeof(msg), 0);
    error("发送注册数据失败", ret);
    // 接受服务器的回复
    struct sockaddr_in serverAddr;
    socklen_t len = sizeof(serverAddr);
    ret = recv(sID, &msg, sizeof(msg), 0);
    if (msg.type == ok)
    {
        printf("教师注册成功\n");
        return 1;
    }
    else
    {
        printf("用户名重复,请重新注册\n");
        return -1;
    }
}
int Login(int sID) // 登录
{
    TEN denglu;
    printf("请输入用户名 密码\n");
    scanf("%s %s", denglu.name, denglu.pwd);
    MSG msg;
    msg.type = TeacherLogin;
    memcpy(msg.buf, &denglu, sizeof(TEN)); // 把注册结构体拷贝到消息结构体的仓库中
    int ret = send(sID, &msg, sizeof(msg), 0);
    error("发送登录数据失败", ret);
    // 接受服务器的回复
    struct sockaddr_in serverAddr;
    socklen_t len = sizeof(serverAddr);
    ret = recv(sID, &msg, sizeof(msg), 0);
    if (msg.type == ok)
    {
        printf("教师登陆成功\n");
        strcpy(LoginUserName, denglu.name); // 把用户名保存到全局变量中，其他地方都可以使用
        showMenu();
        return 1;
    }
    else
    {
        printf("登录失败,请重新登录\n");
        return -1;
    }
}
void PrivateChat(int sID) // 私聊
{
    MSG msg;
    PVCH sl;
    strcpy(sl.selfName, LoginUserName); // 自己的名字
    msg.type = inprivate;               // 修改自己私聊状态
    memcpy(msg.buf, sl.selfName, sizeof(sl));
    int ret = send(sID, &msg, sizeof(msg), 0);
    if (ret <= 0)
    {
        printf("发送数据失败\n");
        return;
    }
    printf("请输入要私聊的对象\n");
    scanf("%s", sl.destName); // 私聊对象名字
    msg.type = Inquire;
    memcpy(msg.buf, &sl, sizeof(sl));
    ret = send(sID, &msg, sizeof(msg), 0);
    if (ret <= 0)
    {
        printf("发送数据失败\n");
        return;
    }
    struct sockaddr_in serverAddr;
    socklen_t len = sizeof(serverAddr);
    ret = recv(sID, &msg, sizeof(msg), 0);
    if (ret <= 0)
    {
        printf("发送数据失败\n");
        return;
    }
    if (msg.type == ok)
    {
        printf("请输入聊天的内容\n");
        pthread_t pt; // 读取服务器返回的消息
        // 启动一个接受消息的线程
        pthread_create(&pt, NULL, work, &sID);
        while (1)
        {
            scanf("%s", sl.text);
            msg.type = privatechat; // 消息类型为单聊
            if (strcmp(sl.text, "sb") == 0)
            {
                strcpy(sl.text, "**");
            }
            // 把单聊的内容拷贝到消息的仓库中
            memcpy(msg.buf, &sl, sizeof(sl));
            // 把消息发送给服务器
            ret = send(sID, &msg, sizeof(msg), 0);
            if (ret <= 0)
            {
                printf("发送数据失败\n");
                return;
            }
            if (strcmp(sl.text, "quit") == 0)
            {
                pthread_cancel(pt);
                msg.type = outprivate;
                ret = send(sID, &msg, sizeof(msg), 0);
                if (ret <= 0)
                {
                    printf("发送数据失败\n");
                    return;
                }
                return;
            }
        }
    }
    else if (msg.type == no)
    {
        printf("对方离线,请留言\n");
        while (1)
        {
            scanf("%s", sl.text);
            msg.type = message;
            // 把单聊的内容拷贝到消息的仓库中
            memcpy(msg.buf, &sl, sizeof(sl));

            // 把消息发送给服务器
            ret = send(sID, &msg, sizeof(msg), 0);
            if (ret <= 0)
            {
                printf("发送数据失败\n");
                return;
            }
            if (strcmp(sl.text, "quit") == 0)
            {
                msg.type = outprivate;
                ret = send(sID, &msg, sizeof(msg), 0);
                if (ret <= 0)
                {
                    printf("发送数据失败\n");
                    return;
                }
                return;
            }
        }
    }
    else if (msg.type == notfind)
    {
        printf("对方不存在\n");
        msg.type = outprivate;
        ret = send(sID, &msg, sizeof(msg), 0);
        if (ret <= 0)
        {
            printf("发送数据失败\n");
            return;
        }
        return;
    }
}
void GroupChat(int sID) // 群聊
{
    pthread_t pt; // 读取服务器返回的消息
    MSG msg;
    PVCH sl;
    strcpy(sl.selfName, LoginUserName); // 自己的名字
    // 启动一个接受消息的线程
    pthread_create(&pt, NULL, work, &sID);
    printf("请输入聊天的内容\n");
    while (1)
    {
        scanf("%s", sl.text);
        msg.type = groupchat; // 消息类型为群聊
        // 把群聊的内容拷贝到消息的仓库中
        memcpy(msg.buf, &sl, sizeof(sl));

        // 把消息发送给服务器
        int ret = send(sID, &msg, sizeof(msg), 0);
        if (ret <= 0)
        {
            printf("发送数据失败\n");
            return;
        }
        if (strcmp(sl.text, "quit") == 0)
        {
            pthread_cancel(pt);
            break;
        }
    }
}
void ShowMessage(int sID) // 查看留言
{
    MSG msg;
    msg.type = viewmessage;
    strcpy(msg.buf, LoginUserName);
    int ret = send(SID, &msg, sizeof(msg), 0);
    if (ret <= 0)
    {
        printf("发送数据失败\n");
        return;
    }
    msg.type = 100000; // 先把消息类型清空
    ret = 0;
    struct sockaddr_in serverAddr;
    socklen_t len = sizeof(serverAddr);
    while (0 < (ret = recv(sID, &msg, sizeof(msg), 0)))
    {
        if (msg.type == viewover) // 查询结束
        {
            printf("------------------------------------------------\n");
            msg.type = delemessage;
            strcpy(msg.buf, LoginUserName);
            int ret = send(SID, &msg, sizeof(msg), 0);
            if (ret <= 0)
            {
                printf("发送数据失败\n");
                return;
            }
            break;
        }
        else if (msg.type == viewmessage) // 查看留言
        {
            PVCH *pIn = (PVCH *)msg.buf;
            printf("------------------------------------------------\n");
            printf(" %s %s %s\n", pIn->selfName, pIn->text, pIn->t);
        }
        else if (msg.type == no)
        {
            printf("没有留言\n");
            return;
        }
    }
}
void Homework(int sID) // 布置作业
{
    MSG msg;
    HWORK hw;
    msg.type = homework;
    strcpy(hw.teacher, LoginUserName); // 自己的名字
    printf("请输入要布置的作业\n");
    scanf("%s", hw.text);
    memcpy(msg.buf, &hw, sizeof(HWORK));
    ret = send(sID, &msg, sizeof(msg), 0);
    if (ret <= 0)
    {
        printf("发送数据失败\n");
        return;
    }
}
void CorrectHomework(int sID) // 批改作业
{
    MSG msg;
    HWORK hw;
    msg.type = viewdohomework;
    strcpy(msg.buf, LoginUserName);
    ret = send(sID, &msg, sizeof(msg), 0);
    if (ret <= 0)
    {
        printf("发送数据失败\n");
        return;
    }
    struct sockaddr_in serverAddr;
    socklen_t len = sizeof(serverAddr);
    while (0 < (ret = recv(sID, &msg, sizeof(msg), 0)))
    {
        if (msg.type == viewover) // 查询结束
        {
            break;
        }
        else if (msg.type == viewdohomework) // 查看作业
        {
            HWORK *pIn = (HWORK *)msg.buf;
            printf(" 学生:%s 科目: %s 答案:%s\n", pIn->student, pIn->subjects, pIn->text);
            printf("答案是否正确(y/n)\n");
            scanf("%s", pIn->yorno);
            msg.type = changescore;
            memcpy(msg.buf, pIn, sizeof(HWORK));
            ret = send(sID, &msg, sizeof(msg), 0);
            if (ret <= 0)
            {
                printf("发送数据失败\n");
                return;
            }
        }
        else if (msg.type == no)
        {
            printf("还没有学生提交\n");
            return;
        }
    }
}
void showinformation(int sID) // 显示信息
{
    MSG msg;
    msg.type = viewteacher;
    strcpy(msg.buf, LoginUserName);
    ret = send(sID, &msg, sizeof(msg), 0);
    if (ret <= 0)
    {
        printf("发送数据失败\n");
        return;
    }
    struct sockaddr_in serverAddr;
    socklen_t len = sizeof(serverAddr);
    ret = recv(sID, &msg, sizeof(msg), 0);
    TEN *pIn = (TEN *)msg.buf;
    printf(" 名字:%s 密码:%s 性别:%s 所教科目:%s 工资:%d 评分:%d\n", pIn->name, pIn->pwd, pIn->sex, pIn->subject, pIn->wages, pIn->score);
}
void showMenu() // 教师界面主菜单
{
    bool loop = true;
    while (loop == true)
    {
        MSG msg;
        msg.type = howmessage;
        memcpy(msg.buf, &LoginUserName, sizeof(LoginUserName));
        int ret = send(SID, &msg, sizeof(msg), 0);
        if (ret <= 0)
        {
            printf("发送数据失败\n");
            return;
        }
        struct sockaddr_in serverAddr;
        socklen_t len = sizeof(serverAddr);
        ret = recv(SID, &msg, sizeof(msg), 0);
        if (ret <= 0)
        {
            printf("接收数据失败\n");
            return;
        }
        char sql[256];
        int num = atoi(msg.buf);
        sprintf(sql, "请选择你要的操作:1.私聊 2.群聊 3.查看留言[%d] 4.布置作业 5.批改作业 6.显示资料 7.❌退出\n", num);
        printf("%s", sql);
        char buf[16];
        scanf("%s", buf);
        if (strcmp(buf, "1") == 0)
        {
            system("clear");
            PrivateChat(SID);
        }
        else if (strcmp(buf, "2") == 0)
        {
            system("clear");
            GroupChat(SID);
        }
        else if (strcmp(buf, "3") == 0)
        {
            system("clear");
            ShowMessage(SID);
        }
        else if (strcmp(buf, "4") == 0)
        {
            system("clear");
            Homework(SID);
        }
        else if (strcmp(buf, "5") == 0)
        {
            system("clear");
            CorrectHomework(SID);
        }
        else if (strcmp(buf, "6") == 0)
        {
            system("clear");
            showinformation(SID);
        }
        else if (strcmp(buf, "7") == 0)
        {
            return;
        }
    }
}
int main(int count, char *arg[])
{
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin)); // 清零
    sin.sin_family = AF_INET;     // IPV4的网络地址版本
    sin.sin_port = htons(9000);   // 把9000号端口转为网络字节序并赋值给端口参数

    u_int32_t ip = 0;
    // 把字符串ip地址转为网络字节序ip
    inet_pton(AF_INET, "192.168.91.60", &ip);
    sin.sin_addr.s_addr = ip;

    // 创建一个tcp套接字，参数1指定地址族，参数2指定协议，SOCK_STREAM代表是TCP，SOCK_DGRAM代表UDP
    int sID = socket(AF_INET, SOCK_STREAM, 0);
    SID = sID;
    while (-1 == connect(sID, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)))
    {
        perror("连接服务器中...");
        sleep(1);
    }

    char buf[128];
    while (1)
    {
        printf("老师您好,欢迎使用本系统\n");
        printf("请选择你要的操作:1.注册 2.登录 3.退出\n");
        scanf("%s", buf);
        if (strcmp(buf, "1") == 0) // 注册
        {
            system("clear");
            Enroll(sID);
        }
        else if (strcmp(buf, "2") == 0)
        {
            system("clear");
            Login(sID);
        }
        else if (strcmp(buf, "3") == 0)
        {
            close(sID);
            return 0;
        }
    }


    return 0;
}